home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
telecomm
/
uemlsrc.arc
/
search.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-08-24
|
26KB
|
764 lines
/*
* The functions in this file
* implement commands that search in the
* forward and backward directions. There are
* no special characters in the search strings.
* Probably should have a regular expression
* search, or something like that.
*/
#include <stdio.h>
#include <ctype.h>
#include "ed.h"
#define CCHR(x) ((x)-'@')
#define SRCH_BEGIN (0) /* Search sub-codes. */
#define SRCH_FORW (-1)
#define SRCH_BACK (-2)
#define SRCH_PREV (-3)
#define SRCH_NEXT (-4)
#define SRCH_NOPR (-5)
#define SRCH_ACCM (-6)
#define NSRCH 128 /* Undoable search commands. */
typedef struct {
int s_code;
LINE *s_dotp;
int s_doto;
} SRCHCOM;
static SRCHCOM cmds[NSRCH];
static int cip;
int srch_lastdir = SRCH_NOPR; /* Last search flags. */
/*
* Search forward.
* Get a search string from the user, and search for it,
* starting at ".". If found, "." gets moved to just after the
* matched characters, and display does all the hard stuff.
* If not found, it just prints a message.
*/
forwsearch(f, n)
register int f, n;
{
if ((f=readpattern("Search", &pat)) != TRUE)
return (f);
if (forwsrch() == FALSE) {
mlwrite("Not found");
return (FALSE);
}
return (TRUE);
}
/*
* Reverse search.
* Get a search string from the user, and search, starting at "."
* and proceeding toward the front of the buffer. If found "." is left
* pointing at the first character of the pattern [the last character that
* was matched].
*/
backsearch(f, n)
register int f, n;
{
if ((f=readpattern("Reverse search", &pat)) != TRUE)
return (f);
if (backsrch() == FALSE) {
mlwrite("Not found");
return (FALSE);
}
return (TRUE);
}
/*
* This routine does the real work of a
* forward search. The pattern is sitting in the external
* variable "pat". If found, dot is updated, the window system
* is notified of the change, and TRUE is returned. If the
* string isn't found, FALSE is returned.
*/
forwsrch()
{
register LINE *clp;
register int cbo;
register LINE *tlp;
register int tbo;
register char *pp;
register int c;
clp = curwp->w_dotp;
cbo = curwp->w_doto;
while (clp != curbp->b_linep) {
if (cbo == llength(clp)) {
clp = lforw(clp);
cbo = 0;
c = '\n';
} else
c = lgetc(clp, cbo++);
if (eq(c, pat[0]) != FALSE) {
tlp = clp;
tbo = cbo;
pp = &pat[1];
while (*pp != 0) {
if (tlp == curbp->b_linep)
goto fail;
if (tbo == llength(tlp)) {
tlp = lforw(tlp);
if (tlp == curbp->b_linep)
goto fail;
tbo = 0;
c = '\n';
} else
c = lgetc(tlp, tbo++);
if (eq(c, *pp++) == FALSE)
goto fail;
}
curwp->w_dotp = tlp;
curwp->w_doto = tbo;
curwp->w_flag |= WFMOVE;
return (TRUE);
}
fail: ;
}
return (FALSE);
}
/*
* This routine does the real work of a
* backward search. The pattern is sitting in the external
* variable "pat". If found, dot is updated, the window system
* is notified of the change, and TRUE is returned. If the
* string isn't found, FALSE is returned.
*/
backsrch()
{
register LINE *clp;
register int cbo;
register LINE *tlp;
register int tbo;
register int c;
register char *epp;
register char *pp;
for (epp = &pat[0]; epp[1] != 0; ++epp)
;
clp = curwp->w_dotp;
cbo = curwp->w_doto;
for (;;) {
if (cbo == 0) {
clp = lback(clp);
if (clp == curbp->b_linep)
return (FALSE);
cbo = llength(clp)+1;
}
if (--cbo == llength(clp))
c = '\n';
else
c = lgetc(clp,cbo);
if (eq(c, *epp) != FALSE) {
tlp = clp;
tbo = cbo;
pp = epp;
while (pp != &pat[0]) {
if (tbo == 0) {
tlp = lback(tlp);
if (tlp == curbp->b_linep)
goto fail;
tbo = llength(tlp)+1;
}
if (--tbo == llength(tlp))
c = '\n';
else
c = lgetc(tlp,tbo);
if (eq(c, *--pp) == FALSE)
goto fail;
}
curwp->w_dotp = tlp;
curwp->w_doto = tbo;
curwp->w_flag |= WFMOVE;
return (TRUE);
}
fail: ;
}
}
/*
* Compare two characters.
* The "bc" comes from the buffer.
* It has it's case folded out. The
* "pc" is from the pattern.
*/
eq(bc, pc)
register int bc;
register int pc;
{
if (bc>='a' && bc<='z')
bc -= 0x20;
if (pc>='a' && pc<='z')
pc -= 0x20;
if (bc == pc)
return (TRUE);
return (FALSE);
}
/*
* Read a pattern.
* Stash it in an external
* variable. The calling function
* passes the address of inpat. The "pat" is
* not updated if the user types in
* an empty line. If the user typed
* an empty line, and there is no
* old pattern, it is an error.
* Display the old pattern, in the
* style of Jeff Lomicka. There is
* some do-it-yourself control
* expansion.
*/
readpattern(prompt, inpat)
char *prompt;
char *inpat;
{
register char *cp1;
register char *cp2;
register int c;
register int s;
char tpat[NPAT+20];
cp1 = &tpat[0]; /* Copy prompt */
cp2 = prompt;
while ((c = *cp2++) != '\0')
*cp1++ = c;
if (inpat[0] != '\0') { /* Old pattern */
*cp1++ = ' ';
*cp1++ = '[';
cp2 = &inpat[0];
while ((c = *cp2++) != 0) {
if (cp1 < &tpat[NPAT+20-6]) { /* "??]: \0" */
if (c<0x20 || c==0x7F) {
*cp1++ = '^';
c ^= 0x40;
} else if (c == '%') /* Map "%" to */
*cp1++ = c; /* "%%". */
*cp1++ = c;
}
}
*cp1++ = ']';
}
*cp1++ = ':'; /* Finish prompt */
*cp1++ = ' ';
*cp1++ = '\0';
s = mlreply(tpat, tpat, NPAT); /* Read pattern */
if (s == TRUE) /* Specified */
strcpy(inpat, tpat);
else if